Popular Searches
Popular Course Categories
Popular Courses

JSON Data in Flutter

Flutter APIs & Networking

 


JSON Data in Flutter


JSON (JavaScript Object Notation) is one of the most commonly used data formats in Flutter applications. It is widely used for exchanging structured data between a Flutter app and a backend API. Flutter applications can decode JSON received from APIs, convert JSON into Dart objects, and encode Dart objects into JSON when sending data to a server.

 

 

1. What is JSON?


JSON stands for JavaScript Object Notation. It is a lightweight, text-based format used to represent structured data.


Although JSON originated from JavaScript, it is language-independent and is commonly used by APIs, mobile applications, web applications, and backend services.

 

 

Example of JSON


{
  "id": 101,
  "name": "Rahul",
  "email": "[email protected]",
  "age": 25
}

 

 

In this example, id, name, email, and age are JSON keys, while their associated values are the actual data.

 

 

2. Why is JSON Important in Flutter?


Flutter applications frequently communicate with REST APIs. Most APIs return data in JSON format, so Flutter developers need to understand how to read, process, create, and send JSON data.



  • Fetching data from REST APIs

  • Sending data to backend servers

  • Reading user information

  • Displaying product information

  • Handling login and registration responses

  • Working with nested API responses

  • Saving structured data

  • Converting Dart objects into API request bodies

  • Converting API responses into Dart model objects

 

 

3. JSON Data Types


JSON supports several basic data types.










JSON Type Example Dart Equivalent
String "Flutter" String
Number 25 int or double
Boolean true bool
Null null null
Object {"name":"Rahul"} Map
Array ["Flutter","Dart"] List

 

 

4. JSON Object


A JSON object contains key-value pairs enclosed in curly braces {}.


{
  "name": "Amit",
  "age": 28,
  "isStudent": false
}

 

 

5. JSON Array


A JSON array contains multiple values and is represented using square brackets [].


[
  "Flutter",
  "Dart",
  "Firebase",
  "REST API"
]

 

 

An array can also contain multiple JSON objects.


[
  {
    "id": 1,
    "name": "Rahul"
  },
  {
    "id": 2,
    "name": "Priya"
  },
  {
    "id": 3,
    "name": "Amit"
  }
]

 

 

6. JSON and Dart


Flutter uses Dart, and Dart provides the dart:convert library for encoding and decoding JSON.


import 'dart:convert';

 

 

The two most important functions are:



  • jsonDecode() - Converts JSON text into Dart data.

  • jsonEncode() - Converts Dart data into JSON text.

 

 

7. Decoding JSON with jsonDecode()


Decoding means converting a JSON string into a Dart data structure.


import 'dart:convert';

 


const jsonString = '''
{
  "name": "Rahul",
  "age": 25
}
''';


final data = jsonDecode(jsonString);


print(data['name']);
print(data['age']);

 

 

Output


Rahul
25

 

 

Flutter's documentation describes manual JSON decoding using the built-in dart:convert library and jsonDecode(). :contentReference[oaicite:0]{index=0}

 

 

8. Understanding jsonDecode()


The result of jsonDecode() is dynamic, so the developer should convert it to an appropriate Dart type when working with structured data.


final Map data =
    jsonDecode(jsonString) as Map;

 


print(data['name']);

 

 

9. Accessing JSON Values


const jsonString = '''
{
  "id": 101,
  "name": "Rahul",
  "email": "[email protected]"
}
''';

 


final data = jsonDecode(jsonString)
    as Map;


print(data['id']);
print(data['name']);
print(data['email']);

 

 

10. Converting JSON Arrays


When the JSON response contains an array, decode it into a Dart list.


const jsonString = '''
[
  {
    "id": 1,
    "name": "Rahul"
  },
  {
    "id": 2,
    "name": "Priya"
  }
]
''';

 


final List users = jsonDecode(jsonString);


for (final user in users) {
  print(user['name']);
}

 

 

11. JSON to Dart Map


A JSON object can be represented in Dart as a Map.


final Map user = {
  'id': 1,
  'name': 'Rahul',
  'age': 25,
};

 

 

12. JSON to Dart List


A JSON array can be represented as a Dart List.


final List skills = [
  'Flutter',
  'Dart',
  'Firebase',
];

 

 

13. Encoding Dart Data into JSON


Encoding means converting Dart data into a JSON string.


import 'dart:convert';

 


final user = {
  'id': 1,
  'name': 'Rahul',
  'email': '[email protected]',
};


final jsonString = jsonEncode(user);


print(jsonString);

 

 

Output


{"id":1,"name":"Rahul","email":"[email protected]"}

 

 

14. JSON Encoding a List


final skills = [
  'Flutter',
  'Dart',
  'Firebase',
];

 


final jsonString = jsonEncode(skills);


print(jsonString);

 

 

Output


["Flutter","Dart","Firebase"]

 

 

15. JSON in HTTP API Responses


A common Flutter API flow looks like this:


Flutter Application
       |
       | HTTP Request
       v
Backend API
       |
       | JSON Response
       v
Flutter Application
       |
       | jsonDecode()
       v
Dart Object / Model
       |
       v
Flutter UI

 

 

16. Fetching JSON from an API


The http package can be used to fetch JSON data from an API.


import 'dart:convert';
import 'package:http/http.dart' as http;

 


Future fetchData() async {
  final response = await http.get(
    Uri.parse(
      'https://jsonplaceholder.typicode.com/albums/1',
    ),
  );


  if (response.statusCode == 200) {
    final data = jsonDecode(response.body)
        as Map;


    print(data['title']);
  } else {
    throw Exception('Failed to load data');
  }
}

 

 

Flutter's networking cookbook follows this general pattern: make the request, check the response status, decode the JSON body, and convert it into a Dart object. :contentReference[oaicite:1]{index=1}

 

 

17. Why Use Dart Model Classes?


Although accessing JSON directly through maps is convenient for small examples, model classes are usually easier to maintain as applications become larger.


Model classes provide:



  • Better type safety

  • Better code completion

  • Cleaner application code

  • Centralized JSON conversion logic

  • Easier testing

  • Better readability

  • More maintainable API code

 

 

18. Creating a Dart Model


Suppose an API returns this JSON:


{
  "id": 1,
  "name": "Rahul",
  "email": "[email protected]"
}

 

 

Create a corresponding Dart class:


class User {
  final int id;
  final String name;
  final String email;

 


  const User({
    required this.id,
    required this.name,
    required this.email,
  });
}

 

 

19. Adding fromJson()


The fromJson() factory constructor converts a JSON map into a Dart object.


class User {
  final int id;
  final String name;
  final String email;

 


  const User({
    required this.id,
    required this.name,
    required this.email,
  });


  factory User.fromJson(Map json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      email: json['email'] as String,
    );
  }
}

 

 

Flutter's JSON documentation recommends model classes with fromJson() and toJson() for stronger type safety and cleaner serialization logic. :contentReference[oaicite:2]{index=2}

 

 

20. Using fromJson()


const jsonString = '''
{
  "id": 1,
  "name": "Rahul",
  "email": "[email protected]"
}
''';

 


final Map data =
    jsonDecode(jsonString);


final user = User.fromJson(data);


print(user.name);
print(user.email);

 

 

21. Adding toJson()


The toJson() method converts a Dart object into a map that can be encoded into JSON.


class User {
  final int id;
  final String name;
  final String email;

 


  const User({
    required this.id,
    required this.name,
    required this.email,
  });


  factory User.fromJson(Map json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      email: json['email'] as String,
    );
  }


  Map toJson() => {
    'id': id,
    'name': name,
    'email': email,
  };
}

 

 

22. Encoding a Model Object


final user = User(
  id: 1,
  name: 'Rahul',
  email: '[email protected]',
);

 


final jsonString = jsonEncode(user.toJson());


print(jsonString);

 

 

23. Complete JSON Model Example


import 'dart:convert';

 


class Product {
  final int id;
  final String name;
  final double price;
  final bool available;


  const Product({
    required this.id,
    required this.name,
    required this.price,
    required this.available,
  });


  factory Product.fromJson(Map json) {
    return Product(
      id: json['id'] as int,
      name: json['name'] as String,
      price: (json['price'] as num).toDouble(),
      available: json['available'] as bool,
    );
  }


  Map toJson() {
    return {
      'id': id,
      'name': name,
      'price': price,
      'available': available,
    };
  }
}


void main() {
  const jsonString = '''
  {
    "id": 1,
    "name": "Flutter Course",
    "price": 4999.0,
    "available": true
  }
  ''';


  final data = jsonDecode(jsonString)
      as Map;


  final product = Product.fromJson(data);


  print(product.name);
  print(product.price);


  final jsonOutput = jsonEncode(product.toJson());


  print(jsonOutput);
}

 

 

24. JSON Arrays and Model Lists


When an API returns multiple objects, convert each JSON object into a model object.


final List data = jsonDecode(response.body);

 


final List products = data
    .map(
      (item) => Product.fromJson(
        item as Map,
      ),
    )
    .toList();

 

 

25. Displaying JSON Data in ListView


ListView.builder(
  itemCount: products.length,
  itemBuilder: (context, index) {
    final product = products[index];

 


    return ListTile(
      title: Text(product.name),
      subtitle: Text('₹${product.price}'),
      trailing: product.available
          ? const Icon(Icons.check)
          : const Icon(Icons.close),
    );
  },
)

 

 

26. Nested JSON Objects


Real-world APIs often contain nested JSON objects.


{
  "id": 1,
  "name": "Rahul",
  "address": {
    "street": "MG Road",
    "city": "Mumbai",
    "zipCode": "400001"
  }
}

 

 

27. Model for Nested JSON


class Address {
  final String street;
  final String city;
  final String zipCode;

 


  const Address({
    required this.street,
    required this.city,
    required this.zipCode,
  });


  factory Address.fromJson(Map json) {
    return Address(
      street: json['street'] as String,
      city: json['city'] as String,
      zipCode: json['zipCode'] as String,
    );
  }


  Map toJson() => {
    'street': street,
    'city': city,
    'zipCode': zipCode,
  };
}

 

 

28. User Model with Nested Address


class User {
  final int id;
  final String name;
  final Address address;

 


  const User({
    required this.id,
    required this.name,
    required this.address,
  });


  factory User.fromJson(Map json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      address: Address.fromJson(
        json['address'] as Map,
      ),
    );
  }


  Map toJson() => {
    'id': id,
    'name': name,
    'address': address.toJson(),
  };
}

 

 

29. Nested JSON Arrays


JSON can contain arrays inside objects.


{
  "id": 1,
  "name": "Rahul",
  "skills": [
    "Flutter",
    "Dart",
    "Firebase"
  ]
}

 

 

Dart Model


class User {
  final int id;
  final String name;
  final List skills;

 


  const User({
    required this.id,
    required this.name,
    required this.skills,
  });


  factory User.fromJson(Map json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      skills: List.from(
        json['skills'] as List,
      ),
    );
  }
}

 

 

30. Nullable JSON Fields


API responses may contain null values. Dart's null safety should be considered when defining models.


{
  "id": 1,
  "name": "Rahul",
  "phone": null
}

 

 

Dart Model


class User {
  final int id;
  final String name;
  final String? phone;

 


  const User({
    required this.id,
    required this.name,
    this.phone,
  });


  factory User.fromJson(Map json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      phone: json['phone'] as String?,
    );
  }
}

 

 

31. Providing Default Values


Sometimes an API field may be missing. A default value can be used when appropriate.


class User {
  final String name;
  final String role;

 


  const User({
    required this.name,
    required this.role,
  });


  factory User.fromJson(Map json) {
    return User(
      name: json['name'] as String? ?? 'Unknown',
      role: json['role'] as String? ?? 'User',
    );
  }
}

 

 

32. Handling Numbers in JSON


JSON numbers may represent integers or floating-point values. Using num can be useful when the API may return either representation.


final price = (json['price'] as num).toDouble();

 

 

This is useful when an API may return values such as 4999 or 4999.50.

 

 

33. Handling Boolean Values


{
  "name": "Flutter Course",
  "isActive": true
}

 

 

final isActive = json['isActive'] as bool;

 

 

34. Handling Date Strings


JSON does not have a dedicated DateTime type. APIs commonly send dates as strings.


{
  "createdAt": "2026-09-19T10:30:00Z"
}

 

 

Convert the value to a Dart DateTime:


final createdAt = DateTime.parse(
  json['createdAt'] as String,
);

 

 

35. JSON Parsing Errors


JSON parsing can fail when the response is malformed or has an unexpected structure.


try {
  final data = jsonDecode(response.body);
  print(data);
} catch (e) {
  print('Invalid JSON: $e');
}

 

 

36. Handling Unexpected JSON Types


Always be careful about the data types returned by an API.


final age = json['age'];

 


if (age is int) {
  print('Age: $age');
} else {
  print('Invalid age value');
}

 

 

37. JSON and FutureBuilder


FutureBuilder can be used to display JSON data after an asynchronous API request completes.


FutureBuilder(
  future: fetchProduct(),
  builder: (context, snapshot) {
    if (snapshot.connectionState ==
        ConnectionState.waiting) {
      return const CircularProgressIndicator();
    }

 


    if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    }


    if (!snapshot.hasData) {
      return const Text('No product found');
    }


    final product = snapshot.data!;


    return Column(
      children: [
        Text(product.name),
        Text('₹${product.price}'),
      ],
    );
  },
)

 

 

38. JSON and POST Requests


JSON is not only used for API responses. It is also commonly used as the request body when sending data to an API.


import 'dart:convert';
import 'package:http/http.dart' as http;

 


Future createUser() async {
  final user = {
    'name': 'Rahul',
    'email': '[email protected]',
  };


  final response = await http.post(
    Uri.parse('https://example.com/api/users'),
    headers: {
      'Content-Type': 'application/json',
    },
    body: jsonEncode(user),
  );


  print(response.statusCode);
}

 

 

Flutter's networking documentation uses jsonEncode() to convert Dart data into a JSON request body for POST operations. :contentReference[oaicite:3]{index=3}

 

 

39. JSON and API Error Responses


APIs may return errors in JSON format.


{
  "success": false,
  "message": "Invalid email address",
  "errors": {
    "email": "Please enter a valid email"
  }
}

 

 

Reading the Error


final data = jsonDecode(response.body)
    as Map;

 


final message = data['message'] as String?;


print(message);

 

 

40. Creating an API Response Model


For complex APIs, it can be useful to create a separate model for API response information.


class ApiResponse {
  final bool success;
  final String message;

 


  const ApiResponse({
    required this.success,
    required this.message,
  });


  factory ApiResponse.fromJson(
    Map json,
  ) {
    return ApiResponse(
      success: json['success'] as bool? ?? false,
      message: json['message'] as String? ?? '',
    );
  }
}

 

 

41. JSON Serialization vs Deserialization








Operation Description Common Function
Decoding JSON string → Dart data jsonDecode()
Encoding Dart data → JSON string jsonEncode()
Deserialization JSON data → Dart model object fromJson()
Serialization Dart model object → JSON-compatible data toJson()

 

 

42. Manual JSON Serialization


Manual serialization means writing fromJson() and toJson() methods yourself.


class Product {
  final int id;
  final String name;

 


  const Product({
    required this.id,
    required this.name,
  });


  factory Product.fromJson(Map json) {
    return Product(
      id: json['id'] as int,
      name: json['name'] as String,
    );
  }


  Map toJson() => {
    'id': id,
    'name': name,
  };
}

 

 

Manual serialization is simple and useful for smaller projects or prototypes. Flutter's official documentation describes this approach using dart:convert. :contentReference[oaicite:4]{index=4}

 

 

43. JSON Serialization with Code Generation


For medium and large applications with many models, manually writing JSON serialization code can become repetitive. Flutter's documentation discusses code-generation approaches such as json_serializable for larger projects. :contentReference[oaicite:5]{index=5}

 

 

Install json_serializable


flutter pub add json_annotation
flutter pub add --dev build_runner
flutter pub add --dev json_serializable

 

 

44. Using json_serializable


import 'package:json_annotation/json_annotation.dart';

 


part 'user.g.dart';


@JsonSerializable()
class User {
  final String name;
  final String email;


  User({
    required this.name,
    required this.email,
  });


  factory User.fromJson(
    Map json,
  ) => _$UserFromJson(json);


  Map toJson() => _$UserToJson(this);
}

 

 

45. Running Code Generation


After creating a json_serializable model, generate the serialization code using:


dart run build_runner build --delete-conflicting-outputs

 

 

For continuous generation during development:


dart run build_runner watch --delete-conflicting-outputs

 

 

Flutter's JSON documentation provides these commands for generating the .g.dart serialization files. :contentReference[oaicite:6]{index=6}

 

 

46. Mapping Different JSON Key Names


Sometimes an API uses a different naming convention from your Dart model.


For example, an API may return:


{
  "first_name": "Rahul"
}

 

 

With json_serializable, @JsonKey can map the JSON key to a Dart property.


@JsonKey(name: 'first_name')
final String firstName;

 

 

47. Nested Models with Code Generation


Large APIs can contain multiple nested objects. Each nested object can have its own model class.


class Address {
  final String city;

 


  Address({
    required this.city,
  });


  factory Address.fromJson(
    Map json,
  ) => Address(
    city: json['city'] as String,
  );


  Map toJson() => {
    'city': city,
  };
}

 

 

48. JSON Data and Flutter UI


JSON data can be displayed using standard Flutter widgets.


Card(
  child: ListTile(
    title: Text(product.name),
    subtitle: Text('₹${product.price}'),
    trailing: Text(
      product.available ? 'Available' : 'Unavailable',
    ),
  ),
)

 

 

49. JSON Data Flow in a Flutter Application


API Server
    ↓
JSON Response
    ↓
http.Response
    ↓
response.body
    ↓
jsonDecode()
    ↓
Map / List
    ↓
Model.fromJson()
    ↓
Dart Object
    ↓
Application State
    ↓
Flutter Widget
    ↓
User Interface

 

 

50. Complete JSON + API Example


import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

 


class Product {
  final int id;
  final String name;
  final double price;


  const Product({
    required this.id,
    required this.name,
    required this.price,
  });


  factory Product.fromJson(
    Map json,
  ) {
    return Product(
      id: json['id'] as int,
      name: json['name'] as String,
      price: (json['price'] as num).toDouble(),
    );
  }
}


Future> fetchProducts() async {
  final response = await http.get(
    Uri.parse('https://example.com/api/products'),
    headers: {
      'Accept': 'application/json',
    },
  );


  if (response.statusCode != 200) {
    throw Exception('Failed to load products');
  }


  final List data =
      jsonDecode(response.body);


  return data
      .map(
        (item) => Product.fromJson(
          item as Map,
        ),
      )
      .toList();
}


class ProductScreen extends StatefulWidget {
  const ProductScreen({super.key});


  @override
  State createState() =>
      _ProductScreenState();
}


class _ProductScreenState
    extends State {
  late Future> productsFuture;


  @override
  void initState() {
    super.initState();
    productsFuture = fetchProducts();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Products'),
      ),
      body: FutureBuilder>(
        future: productsFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState ==
              ConnectionState.waiting) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }


          if (snapshot.hasError) {
            return Center(
              child: Text('Error: ${snapshot.error}'),
            );
          }


          final products = snapshot.data ?? [];


          if (products.isEmpty) {
            return const Center(
              child: Text('No products found'),
            );
          }


          return ListView.builder(
            itemCount: products.length,
            itemBuilder: (context, index) {
              final product = products[index];


              return ListTile(
                title: Text(product.name),
                subtitle: Text(
                  '₹${product.price}',
                ),
              );
            },
          );
        },
      ),
    );
  }
}

 

 

51. Parsing Large JSON Data


Large JSON responses can require significant processing. For very large datasets, expensive JSON parsing can be moved to another isolate so the user interface remains responsive.


import 'dart:convert';
import 'package:flutter/foundation.dart';

 


List> parseJson(
  String responseBody,
) {
  final data = jsonDecode(responseBody) as List;


  return data
      .map(
        (item) => item as Map,
      )
      .toList();
}


final result = await compute(
  parseJson,
  response.body,
);

 

 

Flutter's networking documentation demonstrates using compute() to move JSON parsing work to another isolate when appropriate for large responses. :contentReference[oaicite:7]{index=7}

 

 

52. JSON Best Practices



  • Use jsonDecode() to decode JSON strings.

  • Use jsonEncode() to encode Dart data.

  • Use model classes for structured API data.

  • Use fromJson() to create model objects.

  • Use toJson() to convert models into JSON-compatible maps.

  • Handle nullable fields carefully.

  • Validate important data types.

  • Handle malformed or unexpected JSON responses.

  • Check HTTP status codes before parsing successful responses.

  • Keep JSON parsing logic outside UI widgets when possible.

  • Use code generation for larger projects when it reduces repetitive serialization code.

  • Use background parsing for very large JSON responses when necessary.

  • Write tests for important serialization and deserialization logic.

 

 

53. Common JSON Mistakes



  • Forgetting to import dart:convert.

  • Using jsonDecode() without checking the response.

  • Assuming every JSON field has the expected type.

  • Ignoring null values.

  • Forgetting to convert nested JSON objects into their models.

  • Trying to access a list as if it were a map.

  • Trying to access a map as if it were a list.

  • Not handling malformed JSON.

  • Putting all JSON parsing logic inside UI widgets.

  • Creating large amounts of repetitive manual serialization code in a large application.

 

 

54. JSON Map vs List








JSON Structure Dart Structure Example
Object Map User information
Array List List of users
Nested Object Nested Map or Model User address
Nested Array List inside Map/Model User skills

 

 

55. Practice Exercise


Create a Flutter application that consumes a product API.



  1. Fetch a JSON list of products.

  1. Create a Product model.

  1. Implement Product.fromJson().

  1. Convert the JSON array into List.

  1. Display the products using ListView.builder.

  1. Show a loading indicator while the API request is running.

  1. Show an error message if JSON parsing fails.

  1. Handle an empty product list.

  1. Add a product search feature.

  1. Add a POST request to create a new product.

  1. Implement toJson() for the product model.

 

 

56. Interview Questions



  1. What is JSON?

  1. Why is JSON commonly used in Flutter applications?

  1. What is the difference between JSON encoding and decoding?

  1. What is jsonDecode()?

  1. What is jsonEncode()?

  1. Which Dart library provides JSON encoding and decoding?

  1. How do you convert JSON into a Dart object?

  1. What is the purpose of fromJson()?

  1. What is the purpose of toJson()?

  1. How do you parse a JSON array?

  1. How do you handle nested JSON?

  1. How do you handle nullable JSON fields?

  1. Why are model classes useful for JSON parsing?

  1. What is manual JSON serialization?

  1. What is json_serializable?

  1. When should code generation be considered for JSON serialization?

  1. How can large JSON responses be parsed without blocking the UI?

  1. How do you convert an API response into a list of Dart objects?

  1. How do you send JSON data using a POST request?

  1. How do you handle invalid JSON?

 

 

57. Quick Revision















Concept Key Point
JSON Lightweight format for structured data exchange
dart:convert Dart library containing JSON encoding and decoding utilities
jsonDecode() Converts JSON text into Dart data
jsonEncode() Converts Dart data into JSON text
fromJson() Creates a Dart model from JSON data
toJson() Converts a Dart model into JSON-compatible data
Map Represents a JSON object
List Represents a JSON array
Model Class Provides structured representation of API data
json_serializable Generates JSON serialization code
compute() Can move expensive parsing work to another isolate

 

 

58. Official Flutter Resources








 

 

59. Learn Flutter with JustAcademy


To learn Flutter development through structured training, visit the JustAcademy Flutter Training Course.


To register for a Flutter course demonstration, visit the JustAcademy Flutter Course Demo Registration page.

 

 

Conclusion


JSON is a fundamental part of Flutter application development because it provides a standard way to exchange structured data between Flutter applications and backend services. Developers should understand JSON objects, arrays, data types, jsonDecode(), jsonEncode(), model classes, fromJson(), toJson(), nested JSON, nullable values, error handling, and JSON serialization.


For small projects, manual serialization with dart:convert can be straightforward. For medium and large applications, code-generation approaches such as json_serializable can reduce repetitive serialization code. :contentReference[oaicite:8]{index=8}


The basic JSON workflow can be remembered as:


API Response
     ↓
JSON String
     ↓
jsonDecode()
     ↓
Map / List
     ↓
fromJson()
     ↓
Dart Model
     ↓
Application State
     ↓
Flutter UI

 

whatsapp